﻿/*
 *  Renderer.cpp
 *
 *	Date: 2011-4-23
 *  Author: linshenqi
 */

#include "stdafx.h"
#include "./UIBase.h"

Renderer::Renderer()
: m_pWnd(NULL)
, m_pDC(NULL)
{
	m_MemDC.DeleteDC();
}

Renderer::~Renderer()
{
	UnSetDC();
}

void Renderer::SetDC(CDC *pDC)
{
	if(!m_pWnd)
		return;

	if(m_pDC)
	{
		m_pWnd->ReleaseDC(m_pDC);
	}
	m_MemDC.DeleteDC();
		
	m_pDC = m_pWnd->GetDC();
	m_MemDC.CreateCompatibleDC(m_pDC);
}

void Renderer::SetBaseWindow(CWnd *pWnd)
{
	m_pWnd = pWnd;
}

void Renderer::DrawRect(const CRect *pRect, const GRAPHICPROP *pProp,  CDC *pSelectDC, CDC *pDrawDC, BYTE nFlag)
{
	//if(!m_pDC)
		//return;

	//CDC *pSelectDC, *pDrawDC;
	if(!pSelectDC || !pDrawDC)
	{
		if(nFlag == DRAW)
		{
			pSelectDC = m_pDC;
			pDrawDC = m_pDC;
		}
		else
		{
			pSelectDC = &m_MemDC;
			pDrawDC = &m_MemDC;
		}
	}

	CPen pen(pProp->Style, pProp->FrameWidth, pProp->clrFrame);
	CPen *oldPen = pSelectDC->SelectObject(&pen);
	CBrush brush(pProp->clrFill);
	CBrush *oldBrush = pSelectDC->SelectObject(&brush);
	
	pDrawDC->Rectangle(pRect);
	
	pSelectDC->SelectObject(oldPen);
	pSelectDC->SelectObject(oldBrush);
}

void Renderer::DrawRoundRect(const CRect *pRect, const GRAPHICPROP *pProp, CPoint pt, CDC *pSelectDC, CDC *pDrawDC, BYTE nFlag)
{
	if(!pSelectDC || !pDrawDC)
	{
		if(nFlag == DRAW)
		{
			pSelectDC = m_pDC;
			pDrawDC = m_pDC;
		}
		else
		{
			pSelectDC = &m_MemDC;
			pDrawDC = &m_MemDC;
		}
	}

	CPen pen(pProp->Style, pProp->FrameWidth, pProp->clrFrame);
	CPen *oldPen = pSelectDC->SelectObject(&pen);
	CBrush brush(pProp->clrFill);
	CBrush *oldBrush = pSelectDC->SelectObject(&brush);
	
	pDrawDC->RoundRect(pRect, pt);
	
	pSelectDC->SelectObject(oldPen);
	pSelectDC->SelectObject(oldBrush);
}

void Renderer::DrawTransparentRect(const CRect *pRect, const GRAPHICPROP *pProp, CDC *pSelectDC, CDC *pDrawDC, BYTE nFlag)
{
	if(!pSelectDC || !pDrawDC)
	{
		if(nFlag == DRAW)
		{
			pSelectDC = m_pDC;
			pDrawDC = m_pDC;
		}
		else
		{
			pSelectDC = &m_MemDC;
			pDrawDC = &m_MemDC;
		}
	}

	CPen pen(pProp->Style, pProp->FrameWidth, pProp->clrFrame);
	CBrush brush;
	brush.CreateStockObject(NULL_BRUSH);
	CPen *oldPen = pSelectDC->SelectObject(&pen);
	CBrush *oldBrush = pSelectDC->SelectObject(&brush);
	
	pDrawDC->RoundRect(pRect, CPoint(12, 12));
	
	pSelectDC->SelectObject(oldPen);
	pSelectDC->SelectObject(oldBrush);
}

void Renderer::DrawEllipse(const CRect *pRect, const GRAPHICPROP *pProp,  CDC *pSelectDC, CDC *pDrawDC, BYTE nFlag)
{
	//if(!m_pDC)
		//return;

	//CDC *pSelectDC, *pDrawDC;
	if(!pSelectDC || !pDrawDC)
	{
		if(nFlag == DRAW)
		{
			pSelectDC = m_pDC;
			pDrawDC = m_pDC;
		}
		else
		{
			pSelectDC = &m_MemDC;
			pDrawDC = &m_MemDC;
		}
	}

	CPen pen(pProp->Style, pProp->FrameWidth, pProp->clrFrame);
	CPen *oldPen = pSelectDC->SelectObject(&pen);
	CBrush brush(pProp->clrFill);
	CBrush *oldBrush = pSelectDC->SelectObject(&brush);
	
	pDrawDC->Ellipse(pRect);

	pSelectDC->SelectObject(oldPen);
	pSelectDC->SelectObject(oldBrush);
}

void Renderer::DrawPolygon(const POINT *lpPts, int nCounts, const GRAPHICPROP *pProp, CDC *pSelectDC, CDC *pDrawDC, BYTE nFlag)
{
	if(!pSelectDC || !pDrawDC)
	{
		if(nFlag == DRAW)
		{
			pSelectDC = m_pDC;
			pDrawDC = m_pDC;
		}
		else
		{
			pSelectDC = &m_MemDC;
			pDrawDC = &m_MemDC;
		}
	}

	CPen pen(pProp->Style, pProp->FrameWidth, pProp->clrFrame);
	CPen *oldPen = pSelectDC->SelectObject(&pen);
	CBrush brush(pProp->clrFill);
	CBrush *oldBrush = pSelectDC->SelectObject(&brush);
	
	pDrawDC->Polygon(lpPts, nCounts);

	pSelectDC->SelectObject(oldPen);
	pSelectDC->SelectObject(oldBrush);
}

bool Renderer::PtInPolygon(POINT p, POINT *ptPolygon, int nCount)
{
	int nCross = 0;
	for (int i = 0; i < nCount; i++) 
	{
		POINT p1 = ptPolygon[i];
		POINT p2 = ptPolygon[(i + 1) % nCount];

		if ( p1.y == p2.y ) // p1p2 与 y=p0.y平行 
			continue;
		if ( p.y < min(p1.y, p2.y) ) // 交点在p1p2延长线上 
			continue;
		if ( p.y >= max(p1.y, p2.y) ) // 交点在p1p2延长线上
			continue;
		// 求交点的 X 坐标 -------------------------------------------------------------- 
		double x = (double)(p.y - p1.y) * (double)(p2.x - p1.x) / (double)(p2.y - p1.y) + p1.x;
		if ( x > p.x ) 
			nCross++; // 只统计单边交点 
	}
	// 单边交点为偶数，点在多边形之外 --- 
	return (nCross % 2 == 1);
}

void Renderer::DrawLine(const CPoint *pStart, const CPoint *pEnd, const GRAPHICPROP *pProp,  CDC *pSelectDC, CDC *pDrawDC, BYTE nFlag)
{
	//if(!m_pDC)
		//return;

	//CDC *pSelectDC, *pDrawDC;
	if(!pSelectDC || !pDrawDC)
	{
		if(nFlag == DRAW)
		{
			pSelectDC = m_pDC;
			pDrawDC = m_pDC;
		}
		else
		{
			pSelectDC = &m_MemDC;
			pDrawDC = &m_MemDC;
		}
	}

	CPen pen(pProp->Style, pProp->FrameWidth, pProp->clrFrame);
	CPen *oldPen = pSelectDC->SelectObject(&pen);

	pDrawDC->MoveTo(*pStart);
	pDrawDC->LineTo(*pEnd);

	pSelectDC->SelectObject(oldPen);
}

void Renderer::DrawText(LOGFONT *pFont, CRect *pRect, CString& str, COLORREF clrColor,  CDC *pSelectDC, CDC *pDrawDC, BYTE nFlag)
{
	//if(!m_pDC)
		//return;

	//CDC *pSelectDC, *pDrawDC;
	if(!pSelectDC || !pDrawDC)
	{
		if(nFlag == DRAW)
		{
			pSelectDC = m_pDC;
			pDrawDC = m_pDC;
		}
		else
		{
			pSelectDC = &m_MemDC;
			pDrawDC = m_pDC;
		}
	}

	CFont font;
	CFont *pOldfont;
	if(pFont)
	{
		font.CreateFontIndirect(pFont);
		pOldfont = pSelectDC->SelectObject(&font);
	}

	pSelectDC->SetBkMode(TRANSPARENT);
	pSelectDC->SetTextColor(clrColor);
	pSelectDC->SetTextAlign(TA_CENTER);
	
	pDrawDC->TextOut(pRect->CenterPoint().x, pRect->CenterPoint().y, str);

	if(pFont)
	{
		pSelectDC->SelectObject(pOldfont);
	}
}

void Renderer::DrawBmp(const CRect *pRect, CBitmap *pBmp,  CDC *pSelectDC, CDC *pDrawDC, int x, int y, BYTE nFlag)
{
	//if(!m_pDC)
		//return;

	//CDC *pSelectDC, *pDrawDC;
	if(!pSelectDC || !pDrawDC)
	{
		if(nFlag == DRAW)
		{
			pSelectDC = &m_MemDC;
			pDrawDC = m_pDC;
		}
		else
		{
			pSelectDC = &m_MemDC;
			pDrawDC = &m_MemDC;
		}
	}
	CRgn rgn;
	rgn.CreateRoundRectRgn(pRect->left, pRect->top, pRect->right, pRect->bottom, x, y);

	CBitmap *oldbmp = pSelectDC->SelectObject(pBmp);
	pDrawDC->SelectClipRgn(&rgn);

	pDrawDC->BitBlt(pRect->left, 
					pRect->top, 
					pRect->Width(), 
					pRect->Height(), 
					pSelectDC, 
					0, 
					0, 
					SRCCOPY);

	pDrawDC->SelectClipRgn(NULL);
	pSelectDC->SelectObject(oldbmp);
	rgn.DeleteObject();
}

bool Renderer::OnPaint(CPaintDC *pDC, CDC *pMemDC)
{
	return true;
}

bool Renderer::OnMouseMove(UINT nFlags, CPoint point)
{
	return true;
}

bool Renderer::OnLButtonDown(UINT nFlags, CPoint point)
{
	return true;
}

bool Renderer::OnLButtonUp(UINT nFlags, CPoint point)
{
	return true;
}

bool Renderer::OnRButtonDown(UINT nFlags, CPoint point)
{
	return true;
}

bool Renderer::OnRButtonUp(UINT nFlags, CPoint point)
{
	return true;
}

bool Renderer::OnLButtonDblClk(UINT nFlags, CPoint point)
{
	return true;
}

void Renderer::UnSetDC()	
{
	if(!this->m_pWnd)
		return;
	::ReleaseDC(this->m_pWnd->GetSafeHwnd(), m_pDC->GetSafeHdc());
	m_MemDC.DeleteDC();
}
